package de.clue.corpus.twitter.treetagger;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Vector;
import java.util.regex.Pattern;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.annolab.tt4j.TokenHandler;
import org.annolab.tt4j.TreeTaggerWrapper;
import org.apache.commons.lang.StringEscapeUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

public class TreeTagger extends org.xml.sax.helpers.DefaultHandler {


	private final String taggerHome;
	private final String modelPath;
	private final String path;
	private final String outputPath;
	private Writer out;
	private boolean foundText;
	private StringBuffer cachedTwitter = new StringBuffer();
	private StringBuffer cachedText = new StringBuffer();

	private TreeTaggerWrapper treeTagger = null;

	public TreeTagger(String taggerHome, String modelPath, String path, String outputPath) {
		this.taggerHome = taggerHome;
		this.modelPath = modelPath;
		this.path = path;
		this.outputPath = outputPath;

		validateArguments();

		initialize();

	}


	private void validateArguments() {
		// TODO Auto-generated method stub

	}

	private void initialize() {
		System.setProperty("treetagger.home", taggerHome);
		treeTagger = new TreeTaggerWrapper<String>();
		try {
			treeTagger.setModel(modelPath);
			treeTagger.setHandler(new TokenHandler<String>() {
				public void token(String token, String pos, String lemma) {
					if(!token.startsWith("http")){
						cachedTwitter.append("<token tag=\""+pos+"\" lemma=\"" + escapeText(lemma) + "\">"+escapeText(token)+"</token>");
						
					} else {
						cachedTwitter.append("<token tag=\"HL\">"+escapeText(token)+"</token>");
						
					}
					
				}
			});

		} catch (Exception e) {
			e.printStackTrace();

		}

	}

	public void process(){
		tagFilesInDirectory();

	}

	private void tagFilesInDirectory() {
		File sourceDirectory = new File(path);
		String[] list = sourceDirectory.list();

		for (int i = 0; i < list.length; i++) {
			try {
				String currentFileName = list[i];
				File currentFile = new File(path,currentFileName);
				if(currentFile.isFile()){
					System.out.println("Processing file: " + currentFile.getAbsolutePath());

					try {
						out = new BufferedWriter(new OutputStreamWriter(
								new FileOutputStream(outputPath + System.getProperty("file.separator") + currentFileName), "UTF8"));

						out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
//						out.write("<root>");
						out.write(System.getProperty("line.separator"));

					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}

					readFile(currentFile);

					try {
						out.write("</root>");
						out.flush();
						out.close();
						out = null;
					} catch (Exception e) {
						e.printStackTrace();
					}
					
					cachedText = new StringBuffer();
					cachedTwitter = new StringBuffer();

					System.out.println("File checked!");

				}
			} catch (Exception e) {
				e.printStackTrace();

			}

		}

	}

	private void readFile(File file) throws Exception{

		// Factory um parser zu erzeugen
		SAXParserFactory factory = SAXParserFactory.newInstance();
		// Parser um datei zu parsen
		SAXParser saxParser = factory.newSAXParser();

		// Parse Datei; Parameter sind: Dateiname und Handler
		saxParser.parse(file, this);

	}

	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {

		if (qName.equalsIgnoreCase("root")) {
			//				System.out.println(">>>> START <<<<<<<");
		}

		if (qName.equalsIgnoreCase("tweet")) {
			// System.out.println(" ### Tweet ###");
		}
		if (qName.equalsIgnoreCase("text")) {
			foundText = true;
		}


		cachedTwitter.append("<" + qName + ">");

	}

	public void endElement(String uri, String localName, String name)
	throws SAXException {

		

		if (name.equalsIgnoreCase("text")) {
			foundText = false;
			// (!!!!!!!!!!!!!!)hier taggen

			try {
				String text = cachedText.toString();
				cachedText = new StringBuffer();
				// tokenize
				//				String[] textArray = Pattern.compile("\\s").split(text);
//				String[] textArray = Pattern.compile("(?<=[\\s\\W])|(?=[\\s\\W])").split(text);
				String[] textArraySpaces = Pattern.compile("\\s").split(text);
				
				// additional characters
				Vector<String> textVector = new Vector<String>();
				for (int i = 0; i < textArraySpaces.length; i++) {
					String currentText = textArraySpaces[i];
					if(!currentText.startsWith("http")){
						String[] currentTextArray = currentText.split("(?<=[?!-+.,])|(?=[?!-+.,])");
						for (int j = 0; j < currentTextArray.length; j++) {
							textVector.add(currentTextArray[j]);
						}
					} else {
						textVector.add(currentText);
					}
				}
					
				
				
				// remove empty strings
				Vector<String> textVectorFinal = new Vector<String>();
				for(String currentString:textVector){
					if(!"".equals(currentString.trim())){
						textVectorFinal.add(currentString.trim());
						
					}
					
				}
				

				// tag
				//				treeTagger.process(Arrays.asList(textArray));
				treeTagger.process(textVectorFinal);
				

			} catch (Exception e) {
				e.printStackTrace();

			}
			
		}
		
		cachedTwitter.append("</" + name + ">");
		
		if ("tweet".equals(name)) {
			appendToFile(cachedTwitter.toString());

			cachedTwitter = null;
			cachedTwitter = new StringBuffer();
		}
		

	}
	
	private String escapeText(String text){
		String escapedText = "";
		
		escapedText = text.replaceAll("&", "&amp;");
		escapedText = escapedText.replaceAll("\\<", "&lt;");
		escapedText = escapedText.replaceAll("\\>", "&gt;");
		escapedText = escapedText.replaceAll("\"", "&quot;");
		escapedText = escapedText.replaceAll("'", "&apos;");
		
//		escapedText = StringEscapeUtils.escapeXml(text);
		
		
		return escapedText;
		
	}

	public void characters(char[] ch, int start, int length) throws SAXException {

		// den Text des Elements
		String text = new String(ch, start, length);
		

		if (foundText){
			cachedText.append(text);

		} else {
			text = escapeText(text);
			cachedTwitter.append(text);
			
		}

	}

	private void appendToFile(String text) {

		try {

			out.write(text);
//			out.write(System.getProperty("line.separator"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} 

	}

	@Override
	protected void finalize() throws Throwable {
		super.finalize();

		if(treeTagger != null){
			treeTagger.destroy();

		}
	}


}
